package ar.uba.is2.common.mensaje.protocolo.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import ar.uba.is2.common.mensaje.Componente;
import ar.uba.is2.common.mensaje.ContenidoParticionable;
import ar.uba.is2.common.mensaje.Mensaje;
import ar.uba.is2.common.mensaje.TipoMensaje;

public class Buffer {
	
	private int numeroMensaje;
	private int cantidadPartes;
	private Componente origen;
	private Componente destino;
	private Date fechaCreacion;
	private TipoMensaje tipoMensaje;
	private Collection<ContenidoParticionable> contenidos;
	private boolean[] mensajesRecibidos;

	public Buffer(int numeroMensaje, int cantidadPartes, Componente origen, 
			Componente destino, Date fechaCreacion, TipoMensaje tipoMensaje) {
		this.numeroMensaje = numeroMensaje;
		this.cantidadPartes = cantidadPartes;
		this.origen = origen;
		this.destino = destino;
		this.fechaCreacion = fechaCreacion;
		this.tipoMensaje = tipoMensaje;
		this.contenidos = new ArrayList<ContenidoParticionable>();

		this.mensajesRecibidos = new boolean[cantidadPartes];
		for (int i = 0; i < mensajesRecibidos.length; i++) {
			mensajesRecibidos[i] = false;
		}
	}

	public synchronized void append(Mensaje mensaje) {
		int parte = mensaje.getParte();
		
		ContenidoParticionable contenido = (ContenidoParticionable) mensaje.getContenido();
		this.contenidos.add(contenido);
		
		mensajesRecibidos[parte] = true;
	}

	public synchronized boolean estaCompleto() {
		for (int i = 0; i < this.mensajesRecibidos.length; i++) {
			if ( !this.mensajesRecibidos[i] ) {
				return false;
			}
			
		}
		return true;
	}

	public Mensaje reagruparMensaje() {
		Mensaje msj = new Mensaje();
		
		msj.setTipoMensaje(this.tipoMensaje);
		msj.setNumeroMensaje(this.numeroMensaje);
		msj.setCantidadPartes(this.cantidadPartes);
		msj.setOrigen(this.origen);
		msj.setDestino(this.destino);
		msj.setFechaCreacion(this.fechaCreacion);
		
		ContenidoParticionable contenidoCompleto = (ContenidoParticionable) this.tipoMensaje.instanciarContenido();
		
		for (ContenidoParticionable contenido : this.contenidos) {
			contenidoCompleto.juntarContenido(contenido);
		}
		
		msj.setContenido(contenidoCompleto);
		
		return msj;
	}
}
